#pragma once

#include "Connector.h"

#include "Association.h"
#include "Behavior.h"
#include "ConnectorEnd.h"

namespace uml {

Connector::Connector(const QString& umlType)
    : Feature(umlType) {}

void Connector::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    Feature::fromJson(json, errorList);
    JsonSerializable::fromJsonArray(contracts_, "contracts", json, errorList);
    JsonSerializable::fromJsonArray(ends_, "ends", json, errorList);
    kind_ = (ConnectorKind)json.value("kind").toInt((int)kind_);
    JsonSerializable::fromJsonArray(redefinedConnectors_, "redefinedConnectors", json, errorList);
    type_ = JsonSerializable::create<Association>(json.value("type"), errorList);

}

void Connector::toJson(QJsonObject& json) {
    Feature::toJson(json);
    JsonSerializable::toJsonArray(contracts_, "contracts", json);
    JsonSerializable::toJsonArray(ends_, "ends", json);
    json.insert("kind", (int)kind_);
    JsonSerializable::toJsonArray(redefinedConnectors_, "redefinedConnectors", json);
    if (type_) {
        QJsonObject type_json;
        type_->toJson(type_json);
        json.insert("type", type_json);
    }
}

/// <summary>
/// contracts getter
/// The set of Behaviors that specify the valid interaction patterns across the
/// Connector.
/// </summary>
vector<shared_ptr<Behavior>>& Connector::contracts() {
    return contracts_;
}

/// <summary>
/// ends getter
/// A Connector has at least two ConnectorEnds, each representing the participation
/// of instances of the Classifiers typing the ConnectableElements attached to the
/// end. The set of ConnectorEnds is ordered.
/// </summary>
vector<shared_ptr<ConnectorEnd>>& Connector::ends() {
    return ends_;
}

/// <summary>
/// kind getter
/// Indicates the kind of Connector. This is derived: a Connector with one or more
/// ends connected to a Port which is not on a Part and which is not a behavior port
/// is a delegation; otherwise it is an assembly.
/// </summary>
ConnectorKind Connector::kind() const {
    return kind_;
}

/// <summary>
/// kind setter
/// Indicates the kind of Connector. This is derived: a Connector with one or more
/// ends connected to a Port which is not on a Part and which is not a behavior port
/// is a delegation; otherwise it is an assembly.
/// </summary>
void Connector::setKind(ConnectorKind value) {
    kind_ = value;
}

/// <summary>
/// redefinedConnectors getter
/// A Connector may be redefined when its containing Classifier is specialized. The
/// redefining Connector may have a type that specializes the type of the redefined
/// Connector. The types of the ConnectorEnds of the redefining Connector may
/// specialize the types of the ConnectorEnds of the redefined Connector. The
/// properties of the ConnectorEnds of the redefining Connector may be replaced.
/// </summary>
vector<shared_ptr<Connector>>& Connector::redefinedConnectors() {
    return redefinedConnectors_;
}

/// <summary>
/// type getter
/// An optional Association that classifies links corresponding to this Connector.
/// </summary>
shared_ptr<Association> Connector::type() const {
    return type_;
}

/// <summary>
/// type setter
/// An optional Association that classifies links corresponding to this Connector.
/// </summary>
void Connector::setType(shared_ptr<Association> value) {
    type_ = value;
}

} // namespace uml
